//
//  HMRefreshControl.swift
//  Weibo
//
//  Created by teacher on 2017/6/10.
//  Copyright © 2017年 teacher. All rights reserved.
//

import UIKit

//  刷新状态
enum HMRefreshControlType {
    //  下拉刷新
    case normal
    //  松手就刷新
    case pulling
    //  正在刷新
    case refreshing
}

//  设置控件的高度
private let HMRefreshControlHeight: CGFloat = 50

//  自定义下拉刷新控件
class HMRefreshControl: UIControl {
    
    //  记录当前控件刷新状态
    var refreshType: HMRefreshControlType = .normal {
        didSet {
            switch refreshType {
            case .normal:
                print("下拉刷新")
                //  显示下拉箭头，停止风火轮，重置箭头，文字改变下拉刷新
                pullDownImageView.isHidden = false
                indicatorView.stopAnimating()
                messageLabel.text = "下拉刷新"
                UIView.animate(withDuration: 0.25, animations: { 
                    self.pullDownImageView.transform = CGAffineTransform.identity
                }, completion: { (_) in
                    //  重置箭头动画完成的回调
                    //  如果上一次是正在刷新，那么需要重置停留位置
                    //  didSet: oldValue 表示上次保持的值， set方法里面有newValue
                    if oldValue == .refreshing {
                        UIView.animate(withDuration: 0.25, animations: {
                            //  设置停留位置
                            self.currentScrollView?.contentInset.top -= HMRefreshControlHeight
                        })
                    }
                })
                
            case .pulling:
                print("松手就刷新")
                //  箭头调转，文字改成松手就刷新
                UIView.animate(withDuration: 0.25, animations: { 
                    self.pullDownImageView.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
                })
                messageLabel.text = "松手就刷新"
            case .refreshing:
                print("正在刷新")
                //  箭头隐藏，开启风火轮，文字改变成正在刷新
                pullDownImageView.isHidden = true
                indicatorView.startAnimating()
                messageLabel.text = "正在刷新..."
                UIView.animate(withDuration: 0.25, animations: {
                    //  设置停留位置
                    self.currentScrollView?.contentInset.top += HMRefreshControlHeight
                })
                
                //  发送事件，提示: UIContorl可以发送事件
                sendActions(for: .valueChanged)
                
            }
        }
    }
    
    //  记录滚动的视图
    var currentScrollView: UIScrollView?
    
    //  MARK:   --懒加载控件
    //  下拉箭头
    fileprivate lazy var pullDownImageView: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    //  提示信息
    fileprivate lazy var messageLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.text = "下拉刷新"
        label.textColor = UIColor.gray
        return label
    }()
    //  风火轮
    fileprivate lazy var indicatorView: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //  添加控件设置约束
    private func setupUI() {
        backgroundColor = UIColor.red
      
        
        //  添加子控件
        addSubview(pullDownImageView)
        addSubview(messageLabel)
        addSubview(indicatorView)
        
        //  使用手写代码进行autolayout布局
        pullDownImageView.translatesAutoresizingMaskIntoConstraints = false
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        indicatorView.translatesAutoresizingMaskIntoConstraints = false
        
        //  设置约束
        addConstraint(NSLayoutConstraint(item: pullDownImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: pullDownImageView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: -35))
        
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .centerY, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: messageLabel, attribute: .leading, relatedBy: .equal, toItem: pullDownImageView, attribute: .trailing, multiplier: 1, constant: 0))
        
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerY, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerY, multiplier: 1, constant: 0))
        addConstraint(NSLayoutConstraint(item: indicatorView, attribute: .centerX, relatedBy: .equal, toItem: pullDownImageView, attribute: .centerX, multiplier: 1, constant: 0))
        
        
    }
    
    //  结束刷新，重置刷新状态为normal
    func endRefreshing() {
        refreshType = .normal
    }
    
    //  将要添加到父视图上进行回调
    override func willMove(toSuperview newSuperview: UIView?) {
        
        //  提示： 不能设置代理，如果使用代理方式去做，那么外加在给tableView设置代理的时候，会把我们newSuperview（tableView）的代理给覆盖
        
        //  使用kvo-> 监听对象属性值得改变
        //  判断父视图是否可以滚动
        if newSuperview is UIScrollView {
            //  是可以滚动的视图
            //  添加滚动视图内容偏移
            let scrollView = newSuperview as! UIScrollView
            //  使用kvo箭头滚动视图的内容偏移
            scrollView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
            //  设置父视图的宽度作为刷新控件的宽度
            self.frame.size.width = scrollView.frame.size.width
            self.frame.size.height = HMRefreshControlHeight
            //  设置y坐标
            self.frame.origin.y = -HMRefreshControlHeight
            //  记录滚动视图
            currentScrollView = scrollView
        }
    }
    
    //  提供kvo监听方法
    //  keypath： 监听属性
    //  object:   监听属性对应的对象
    //  change:  获取监听参数比如可以通过字典获取（最新）的滚动偏移量
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        let contentOffsetY = currentScrollView!.contentOffset.y
        
        //  拖动状态下只有两种刷新状态，由normal进入pulling， 由pulling进入normal
        if currentScrollView!.isDragging {
            //  由normal进入pulling， 由pulling进入normal
            //  临界点
            //  currentScrollView!.contentInset.top 显示内容的位置距离frame原点的位置
            
            let limitMaxY = -(currentScrollView!.contentInset.top + HMRefreshControlHeight)
            //  默认是normal状态
            if contentOffsetY < limitMaxY && refreshType == .normal {
                print("pullging")
                refreshType = .pulling
            } else if contentOffsetY >= limitMaxY && refreshType == .pulling {
                print("normal")
                refreshType = .normal
            }
            
        } else {
            //  进入正在刷新的条件，1.松手，2.pulling
            if refreshType == .pulling {
                print("正在刷新")
                refreshType = .refreshing
            }
        }
    }
    
    //  移除kvo
    deinit {
        currentScrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }

}
